<?php
namespace App\Admin\Controllers\CustomerDelivery;

use App\Admin\Ajax\CustomerDelivery\DeliveryDemandAjax;
use App\Importer\CustomerDelivery\CnImporter;
use App\Models\Basics\SysPlat;
use App\Models\Basics\SysPlatCountry;
use App\Models\CustomerDelivery\CustomerDelivery;
use App\Models\CustomerDelivery\CustomerDeliveryDetail;
use App\Models\CustomerDelivery\CustomerDeliveryLogistics;
use App\Models\CustomerDelivery\CustomerOrder;
use App\Models\CustomerDelivery\CustomerOrderDetails;
use App\Util\SerialNo;
use App\Models\Basics\SysCountry;
use App\Models\Basics\ExpressChannel;
use App\Models\Basics\ExpressCompany;
use App\Models\Basics\SysArea;
use App\Models\Inventory\InventoryCn;
use App\Models\Product\ProductSku;
use App\Models\Sys\Logs;
use App\Util\RExcel;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Facades\Admin;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Maatwebsite\Excel\Facades\Excel;
use Symfony\Component\HttpFoundation\File\UploadedFile;

class DeliveryCnUploadController extends AdminController{

    protected $title = '国内发货单';

    protected function grid()
    {
        $type = request('type');
        return view('customer-delivery.delivery-cn-upload.index',compact('type'));
    }

    public function upload(Request $request){
        $file = $request->file('source_file');
        if ($file->isValid()) {
            $action = $request->get('action');
            $re = $this->{'_import'.$action}($file);
            if(is_array($re)) {
                if($re['flag']){
                    admin_toastr('文件：'.$re['data'].' 上传成功！');
                }else{
                    admin_toastr($re['data'],'error');
                }
            }else{
                return $re;
            }
        }else{
            admin_toastr('无效文件！','error');
        }
        return back()->withInput();
    }

    /**
     * 发货单
     * @param UploadedFile $file
     * @return array|\Symfony\Component\HttpFoundation\BinaryFileResponse
     */
    private function _importDelivery(UploadedFile $file){
        try{
            $data = Excel::toArray(new CnImporter(),$file);
            $data = $data[0];
            if(!$data)return ['flag' => false,'data' => '请上传包含有数据的文件!'];
            $errors = [];
            $count = 1;
            $arr = [];
            $orders = [];
            foreach($data as $key => $row){
                $count++;
                $remark = $row[0] ? trim($row[0]) : '';
                $orderNo = $row[1] ? trim($row[1]) : '';
                $_country = $row[2] ? trim($row[2]) : '';
                $reCountry = $row[3] ? trim($row[3]) : '';
                $receiver = $row[4] ? trim($row[4]) : '';
                $address = $row[5] ? trim($row[5]) : '';
                $state = $row[6] ? trim($row[6]) : '';
                $city = $row[7] ? trim($row[7]) : '';
                $postcode = $row[8] ? trim($row[8]) : '';
                $phone = $row[9] ? trim($row[9]) : '';
                $sku = $row[10] ? trim($row[10]) : '';
                $applyNum = $row[11] ? trim($row[11]) : '';
                $orderChannel = $row[12] ? trim($row[12]) : 1;
                $orderType = $row[13] ? trim($row[13]) : 1;
                $platId = $row[14] ? trim($row[14]) : 0;
                if(!$orderNo || !$_country || !$reCountry || !$receiver || !$address || !$sku || !$applyNum){
                    $errors[$count] = '必填项为空';
                    continue;
                }
                if(!$orderChannel || !$orderType || !isset($platId)){
                    $errors[$count] = '订单必填项,不能为空';
                    continue;
                }

                $keyExist = $platId.'-'.$orderNo.'-'.$sku;
                if(!in_array($keyExist,$arr)){
                    $arr[$count] = $keyExist;
                }else{
                    $errors[$count] = '重复记录';
                    continue;
                }

                $country = strtoupper($_country);
                $countryId = SysCountry::getIdByCountry($country);
                if(!$countryId){
                    $errors[$count] = $country.'系统不存在该发货国家';
                    continue;
                }
                $areaId = SysCountry::getAreaIdByCountryId($countryId);
                if(!$areaId){
                    $errors[$count] = $country.'系统不存在该（国家）发货站点';
                    continue;
                }

                $ps = ProductSku::getModelByCode($sku);
                if(!$ps){
                    $errors[$count] = $sku.'系统不存在该sku';
                    continue;
                }
                $reCount = CustomerDeliveryDetail::query()->where('order_no',$orderNo)->where('psku_id',$ps->id)->count();
                if($reCount > 0){
                    $errors[$count] = $keyExist.'系统已存在该发货数据';
                    continue;
                }
                if(!array_key_exists($orderNo, $orders)){
                    $orders[$orderNo] = [
                        'order_no'      => $orderNo,
                        'order_at'      => date('Y-m-d 00:00:00'),
                        'order_channel' => $orderChannel,   //订单渠道(1.C端，2.B端)
                        'order_type'    => $orderType,         //订单类型(1.订单，2.寄样)
                        'plat_id'       => $platId,     //订单平台(0:无 1:FBA亚马逊 2:shopify 3:乐天)
                        'country_id'    => $countryId, //发货国家
                        'country_code'  => $country, //国家编码
                        'area_id'       => $areaId, //发货站点
                        'is_create'     => CustomerOrderDetails::CREATE_YES, //是否为自建订单 (0：自动生成订单 1：真实自建订单)
                    ];
                }

                $orders[$orderNo]['detail'][$key] = [
                    'plat_id'   => $platId,
                    'psku_id'   => $ps->id,
                    'order_num' => $applyNum,
                    'apply_num' => $applyNum,
                    'status'    => 3, //订单状态 3: 完全申请
                    'is_create' => CustomerOrderDetails::CREATE_YES, //是否为自建订单 (0：自动生成订单 1：真实自建订单)
                ];

                $orders[$orderNo]['receiver'] = [
                    'country' => $reCountry,
                    'receiver' => $receiver,
                    'address' => $address,
                    'state' => $state,
                    'city' => $city,
                    'postcode' => $postcode,
                    'phone' => $phone,
                ];
            }
            if(empty($orders)){
                $errors[] = '本次上传文件未能导入系统：无符合条件的数据';
            }

            if(empty($errors)){
                $inventoryErrors = [];
                foreach ($orders as $order){

                    DB::beginTransaction();
                    //创建订单相关信息
                    $receivers = array_pop($order); //地址
                    $detail = array_pop($order); //详情
                    $orderObj = CustomerOrder::query()->create($order);
                    $orderObj->detail()->createMany($detail);
                    $orderObj->receiver()->create($receivers);
                    if($orderObj){
                        Logs::logs('customer-order-cn', "创建国内自建订单：{$orderObj->order_no}", $orderObj->id);
                        DB::commit();
                    }else{
                        $inventoryErrors[$orderObj->order_no] ='订单异常';
                        DB::rollBack();
                    }

                    //验证库存、组装发货明细数据
                    $flag = false;
                    $deliveryDetailData = [];
                    foreach($orderObj->detail as $_item){
                        //发货明细
                        $deliveryDetailData[] = [
                            'plat_id'         => $orderObj->plat_id,
                            'order_no'        => $orderObj->order_no,
                            'order_detail_id' => $_item->id,
                            'psku_id'         => $_item->psku_id,
                            'apply_num'       => $_item->apply_num,
                            'delivery_type' => CustomerDelivery::DELIVERY_TYPE_CN,   //发货方式 (3:国内)
                        ];

                        //更新国内库存（库存扣减优先级：out > 其它站点 > public）
                        $inventoryCnFlag = DeliveryDemandAjax::saveCnInventory($_item->toarray(), $orderObj->order_no);
                        if ($inventoryCnFlag == false) break;

                        $flag = true;
                    }
                    if (!$flag) {
                        $inventoryErrors[$orderObj->order_no] = '库存更新失败';
                        DB::rollBack();
                        continue;
                    }

                    //创建发货相关信息
                    $deliveryNo = SerialNo::getOPDNo(); //国内自建订单,生成发货单号
                    $deliveryObj = CustomerDelivery::query()->create([
                        'delivery_no' => $deliveryNo,
                        'plat_id'  => $orderObj->plat_id, //订单平台(0:无 1:FBA亚马逊 2:shopify 3:乐天)
                        'order_no' => $orderObj->order_no,
                        'order_at' => date('Y-m-d 00:00:00'),
                        'area_id' => $areaId,
                        'country_id' => $countryId,
                        'seller_id' => Admin::user()->id,
                        'delivery_type' => CustomerDelivery::DELIVERY_TYPE_CN,   //发货方式 (3:国内)
                        'status' => 1,  //发货状态 (1:待备货)
                        'logistics_status' => 1,//物流状态 (1:待更新 2:已更新)
                    ]);
                    $deliveryObj->detail()->createMany($deliveryDetailData);
                    $deliveryObj->receiver()->create($receivers);
                    if($deliveryObj){
                        Logs::logs('customer-order-cn', "创建国内发货单：{$deliveryObj->delivery_no}", $deliveryObj->id);
                        DB::commit();
                    }else{
                        $inventoryErrors[$orderObj->order_no] = '创建发货单失败';
                        DB::rollBack();
                    }
                }

                if(empty($inventoryErrors)){
                    return ['flag' => true,'data' => $file->getClientOriginalName()];
                }else{
                    return RExcel::importResult($inventoryErrors);
                }
            }else{
                return RExcel::importResult($errors);
            }

        }catch(\Exception $e){
            report($e);
            return ['flag' => false, 'data' => $e->getMessage()];
        }
    }

    /**
     * 上传平台物流信息
     * @param UploadedFile $file
     * @return array|\Symfony\Component\HttpFoundation\BinaryFileResponse
     */
    private function _importLogistics(UploadedFile $file)
    {
        try {
            $data = Excel::toArray(new CnImporter(),$file);
            $data = $data[0];
            if(!$data)return ['flag' => false, 'data' => '请上传包含有数据的文件！'];
            DB::beginTransaction();
            $errors = [];
            $count = 1;
            $arr = [];
            foreach($data as $row){
                $count++;
                $_deliveryNo = $row[0] ? trim($row[0]) : '';
                $expressCompanyId = $row[1] ? trim($row[1]) : '';
                $expressChannelId = $row[2] ? trim($row[2]) : '';
                $trackingNo = $row[3] ? trim($row[3]) : '';
                $totalWeight = $row[4] ? trim($row[4]) : 0;
                $shippingFee = $row[5] ? trim($row[5]) : 0;
                $otherFee = $row[6] ? trim($row[6]) : 0;
                $deliveryAt = $row[7] ? RExcel::toDateTime(trim($row[7])) : date('Y-m-d H:i:s');
                $arrivedAt = $row[8] ? RExcel::toDateTime(trim($row[8])) : date('Y-m-d H:i:s');
                if(!$_deliveryNo || !$expressCompanyId || !$expressChannelId){
                    $errors[$count] = '必填项为空';
                    continue;
                }
                $deliveryNo = strtoupper($_deliveryNo);
                if(!in_array($deliveryNo, $arr)){
                    $arr[$count] = $deliveryNo;
                }else{
                    $errors[$count] = '重复记录';
                    continue;
                }
                if($deliveryAt){
                    if(!strtotime($deliveryAt)){
                        $errors[$count] = "发货日期：".$deliveryAt."格式有误";
                        continue;
                    }
                }
                if($arrivedAt){
                    if(!strtotime($arrivedAt)){
                        $errors[$count] = "到货日期：".$arrivedAt."格式有误";
                        continue;
                    }
                }
                $expressCompanyIdFlag = ExpressCompany::existById($expressCompanyId);
                if(!$expressCompanyIdFlag){
                    $errors[$count] = $expressCompanyId.'系统不存在';
                    continue;
                }
                $expressChannelIdFlag = ExpressChannel::existById($expressChannelId);
                if(!$expressChannelIdFlag){
                    $errors[$count] = $expressChannelId.'系统不存在';
                    continue;
                }

                //发货单
                $deliveryObj = CustomerDelivery::query()->where('delivery_no', $deliveryNo)->first();
                if(!$deliveryObj){
                    $errors[$count] = $_deliveryNo.'发货单不存在';
                    continue;
                }
                if ($deliveryObj->plat_id == SysPlat::PLAT_RAKUTEN) {
                    $errors[$count] = $_deliveryNo.'乐天订单请使用专用乐天物流录入（乐天不可在当前功能使用批量上传）';
                    continue;
                }
                $deliveryObj->logistics_status = 2; //物流状态 (1:待更新 2:已更新)
                if(!$deliveryObj->save()){
                    DB::rollBack();
                    $errors[$count] = $_deliveryNo.'物流录入失败1';
                    continue;
                }

                //发货明细
                $detailObj = CustomerDeliveryDetail::query()->firstOrNew(['delivery_no' => $deliveryObj->delivery_no]);
                if($trackingNo){
                    $detailObj->tracking_no = $trackingNo;
                    $detailObj->sync_status = CustomerDeliveryDetail::SYNC_STATUS_YES; //物流追踪号同步，已同步 (0:未同步 1:已同步)
                }
                if (intval($totalWeight) > 0 || intval($shippingFee) > 0 || intval($otherFee) > 0) {
                    $detailObj->total_weight = $totalWeight ?? 0;
                    $detailObj->shipping_fee = $shippingFee ?? 0;
                    $detailObj->other_fee = $otherFee ?? 0;
                    $detailObj->logistics_fee_status = CustomerDeliveryDetail::LOGISTICS_FEE_YES;  //物流费用，已更新 (0:待更新 1:已更新)
                }
                if(!$detailObj->save()){
                    DB::rollBack();
                    $errors[$count] = $_deliveryNo.'物流录入失败2';
                    continue;
                }

                //发货物流
                $logisticsObj = CustomerDeliveryLogistics::query()->firstOrNew(['delivery_no' => $deliveryObj->delivery_no]);
                $logisticsObj->express_company_id = $expressCompanyId;
                $logisticsObj->area_id = $deliveryObj->area_id;
                $logisticsObj->express_channel_id = $expressChannelId;
                if($trackingNo) $logisticsObj->tracking_no = $trackingNo;
                if($totalWeight) $logisticsObj->total_weight = $totalWeight ?? 0;
                if($shippingFee) $logisticsObj->shipping_fee = $shippingFee ?? 0;
                if($otherFee) $logisticsObj->other_fee = $otherFee ?? 0;
                if($deliveryAt) $logisticsObj->delivered_at = date('Y-m-d H:i:s',strtotime($deliveryAt));
                if($arrivedAt) $logisticsObj->arrived_at = date('Y-m-d H:i:s',strtotime($arrivedAt));
                if(!$logisticsObj->save()){
                    DB::rollBack();
                    $errors[$count] = $_deliveryNo.'物流录入失败3';
                    continue;
                }else{
                    DB::commit();
                }
            }

            if(empty($errors)){
                return ['flag' => true,'data' => $file->getClientOriginalName()];
            }else{
                DB::rollBack();
                return RExcel::importResult($errors);
            }

        } catch (\Exception $e) {
            DB::rollBack();
            report($e);
            return ['flag' => false,'data' => '系统异常!'];
        }
    }

    /**
     * 上传乐天平台物流 （rakuten）
     * @param UploadedFile $file
     * @return array|\Symfony\Component\HttpFoundation\BinaryFileResponse
     */
    private function _importLogisticsRakuten(UploadedFile $file)
    {
        try {
            $data = Excel::toArray(new CnImporter(),$file);
            $data = $data[0];

            if(!$data)return ['flag' => false, 'data' => '请上传包含有数据的文件！'];
            DB::beginTransaction();
            $errors = [];
            $count = 1;
            $arr = [];
            foreach($data as $row){
                $count++;
                $_deliveryNo = $row[0] ? trim($row[0]) : '';
                $expressCompanyId = $row[1] ? trim($row[1]) : '';
                $expressChannelId = $row[2] ? trim($row[2]) : '';
                $trackingNo = $row[3] ? trim($row[3]) : '';
                $totalWeight = $row[4] ? trim($row[4]) : 0;
                $shippingFee = $row[5] ? trim($row[5]) : 0;
                $otherFee = $row[6] ? trim($row[6]) : 0;
                $deliveredAt = $row[7] ? RExcel::toDateTime(trim($row[7])) : date('Y-m-d H:i:s');
                $arrivedAt = $row[8] ? RExcel::toDateTime(trim($row[8])) : date('Y-m-d H:i:s');
                if(!$_deliveryNo || !$expressCompanyId || !$expressChannelId){
                    $errors[$count] = ',必填项为空';
                    continue;
                }
                $orderNo = strtoupper($_deliveryNo);
                if(!in_array($orderNo, $arr)){
                    $arr[$count] = $orderNo;
                }else{
                    $errors[$count] = ',重复记录';
                    continue;
                }
                if($deliveredAt || $arrivedAt){
                    if(!strtotime($deliveredAt)){
                        $errors[$count] = ",发货日期：".$deliveredAt."格式有误";
                        continue;
                    }
                    if(!strtotime($arrivedAt)){
                        $errors[$count] = ",到货日期：".$arrivedAt."格式有误";
                        continue;
                    }
                }

                $expressCompanyIdFlag = ExpressCompany::existById($expressCompanyId);
                if(!$expressCompanyIdFlag){
                    $errors[$count] = $expressCompanyId.'系统不存在该物流公司';
                    continue;
                }
                $expressChannelIdFlag = ExpressChannel::existById($expressChannelId);
                if(!$expressChannelIdFlag){
                    $errors[$count] = $expressChannelId.'系统不存在该物流渠道';
                    continue;
                }

                //发货单
                $deliveryObj = CustomerDelivery::query()->where('order_no', $orderNo)->first();
                if(!$deliveryObj){
                    $errors[$count] = $_deliveryNo.'发货单不存在';
                    continue;
                }
                if ($deliveryObj->plat_id != SysPlat::PLAT_RAKUTEN) {
                    $errors[$count] = $_deliveryNo.'平台异常（仅供乐天平台物流批量上传，请勿上传其他平台订单数据）'; //乐天平台
                    continue;
                }
                $expressCompany = ExpressCompany::getModel($expressCompanyId);
                if(!$expressCompany){
                    $errors[$count] = $expressCompanyId.'物流公司不存在'; //乐天物流公司
                    continue;
                }
                $deliveryObj->logistics_status = 2; //物流状态 (1:待更新 2:已更新)
                if(!$deliveryObj->save()) {
                    $errors[$count] = $_deliveryNo.'物流录入失败1';
                    continue;
                }

                //发货明细
                $detailObj = CustomerDeliveryDetail::query()->firstOrNew(['delivery_no' => $deliveryObj->delivery_no]);
                if($trackingNo) {
                    $detailObj->tracking_no = $trackingNo;
                    $detailObj->sync_status = CustomerDeliveryDetail::SYNC_STATUS_YES; //物流追踪号同步，已同步 (0:未同步 1:已同步)
                }
                if($totalWeight) $detailObj->total_weight = $totalWeight;
                if($shippingFee) $detailObj->shipping_fee = $shippingFee;
                if($otherFee) $detailObj->other_fee = $otherFee;
                if (intval($totalWeight) > 0 || intval($shippingFee) > 0 || intval($otherFee) > 0) {
                    $detailObj->logistics_fee_status = CustomerDeliveryDetail::LOGISTICS_FEE_YES; //物流费用，已更新 (0:未更新 1:已更新)
                }
                if($deliveredAt){
                    $detailObj->shipping_date = date('Y-m-d H:i:s',strtotime($deliveredAt));
                    $detailObj->delivered_at = date('Y-m-d H:i:s',strtotime($deliveredAt));
                }
                $detailObj->logistics_type = $expressCompany->name_en;
                $detailObj->delivery_company = $expressCompany->code;
                if(!$detailObj->save()) {
                    $errors[$count] = $_deliveryNo.'物流录入失败2';
                    continue;
                }

                //发货物流
                $logisticsObj = CustomerDeliveryLogistics::query()->firstOrNew(['delivery_no' => $deliveryObj->delivery_no]);
                $logisticsObj->express_company_id = $expressCompanyId;
                $logisticsObj->area_id = $deliveryObj->area_id;
                $logisticsObj->express_channel_id = $expressChannelId;
                if($trackingNo) $logisticsObj->tracking_no = $trackingNo;
                if($totalWeight) $logisticsObj->total_weight = $totalWeight ?? 0;
                if($shippingFee) $logisticsObj->shipping_fee = $shippingFee ?? 0;
                if($otherFee) $logisticsObj->other_fee = $otherFee ?? 0;
                if($deliveredAt) $logisticsObj->delivered_at = date('Y-m-d H:i:s',strtotime($deliveredAt));
                if(!$logisticsObj->save()){
                    $errors[$count] = $_deliveryNo.'物流录入失败3';
                }else{
                    DB::commit();
                }
            }

            if(empty($errors)){
                return ['flag' => true,'data' => $file->getClientOriginalName()];
            }else{
                return RExcel::importResult($errors);
            }
        } catch (\Exception $e) {
            DB::rollBack();
            report($e);
            return ['flag' => false,'data' => '系统异常!'];
        }
    }


    public function template(Request $request){
        $temp = $request->get('temp');
        $suffix = $request->get('suffix','xlsx');
        return Storage::disk('admin')->download("template/{$temp}-template.{$suffix}");
    }
}
